import { loadJs } from '@/utils';
import CenterPoint from './CenterPoint'
import Pagination from './Pagination'

const emptyResults = {
   type: 'address',
   list: [],
   hasNextPage: false,
}

type Feature = 'bg' | 'point' | 'road' | 'building'
type MapStyle = 'amap://styles/normal' | 'amap://styles/grey' | 'amap://styles/whitesmoke' | 'amap://styles/dark' | 'amap://styles/light' | 'amap://styles/graffiti'
type GdMapOptions = {
   init?: MapOptions,
   extends?: ExtendMapOptions
}
type GetAddressReturnType = Promise<ClickInfo | null>;
type MapOptions = {
   center?: [number, number] // 中心点位
   zoom?: number //初始地图缩放级别
   pitch?: number // 俯仰角
   viewMode?: '2D' | '3D'
   terrain?: boolean // 是否展示地形
   features?: Array<Feature> // 支持 'bg' （地图背景）、 'point' （POI点）、 'road' （道路）、 'building' （建筑物）
   zooms?: [number, number]// 缩放级别
   dragEnable?: boolean // 是否可平移
   zoomEnable?: boolean // 是否可缩放
   mapStyle?: MapStyle // 地图主题
   [k: string]: any
}

export type ClickInfo = {
   citycode?: string
   address: string
   lat: number
   lng: number
}
type ExtendMapOptions = {
   showCenterMarker?: boolean // 显示中心点位
   changeCenterByClick?: boolean // 点击地图时改变中心点位？
   onClickPosition?: (info: ClickInfo) => void // 点击地图的回调
   onInitPosition?: (info: ClickInfo) => void // 初始化的地址信息
   // searchLimitCity?:boolean // 搜索时是否限制在某个城市
}



class GdMap {
   container: string
   // 选项
   initOptions: MapOptions
   extendsOptions: ExtendMapOptions

   AMap: any// 高德地图js
   map: any // 地图实例

   // 中心点位
   center: CenterPoint

   // 插件实例
   MSearch: any // 通过关键词搜索 ,追加了pagination和keyword属性
   Geocoder: any // 通过经纬度搜索 

   constructor(container: string, options?: GdMapOptions) {
      this.container = container
      this.initOptions = options.init || {}
      this.extendsOptions = options.extends || {}
   }

   destroy = () => {
      this.map.destroy()
   }

   /**---------------------------------------初始化---------------------------------------*/

   init = async () => {
      const res = await loadJs('https://webapi.amap.com/loader.js')
      if (res === 'ok') {
         // @ts-ignore
         // 获取js对象
         this.AMap = await AMapLoader.load({
            key: 'd3972b5c1a4a2adbd217b66a37c04227',
            version: '2.0',
         })

         // 初始化地图
         this.map = new this.AMap.Map(this.container, {
            zoom: 16,
            ... this.initOptions
         });

         // 根据选项初始化其他功能

         // 初始化插件
         await this.initGeocoder()
         await this.initMSearch()

         await this.initCenter()
         this.initClickEvent()
      }
   }

   // Geocoder插件
   private initGeocoder = async () => {
      return new Promise((resolve, reject) => {
         this.AMap.plugin('AMap.Geocoder', () => {
            this.Geocoder = new this.AMap.Geocoder();
            resolve(this.Geocoder)
         })
      })
   }

   // MSearch插件
   private initMSearch = async () => {
      return new Promise((resolve, reject) => {
         this.AMap.plugin(['AMap.PlaceSearch'], () => {
            var PlaceSearchOptions = {
               pageSize: 12,
               pageIndex: 1,
            };
            this.MSearch = new this.AMap.PlaceSearch(PlaceSearchOptions); //构造PlaceSearch类
            resolve(this.MSearch)
         });
      })
   }

   // 初始化点击事件
   private initClickEvent = async () => {
      let opts = this.extendsOptions
      this.map.on('click', async (obj) => {
         const { lng, lat } = obj.lnglat;
         // 如果显示了中心点，且要求中心的随着点击改变
         if (opts.showCenterMarker && opts.changeCenterByClick) {
            this.center.setMakerAndShift(lng, lat)
         }

         if (opts.onClickPosition) {
            const result = await this.getGeocoderAddress(lng, lat)
            opts.onClickPosition(result)
         }
      });
   }

   // 初始化中心点与获取中心点信息
   private initCenter = async () => {
      let opts = this.extendsOptions
      const { lng, lat } = this.map.getCenter();
      this.center = new CenterPoint({
         lng,
         lat,
      }, this.AMap, this.map)

      if (opts.showCenterMarker) {
         this.center.setMaker(lng, lat)
      }
      if (opts.onInitPosition) {
         const result = await this.getGeocoderAddress(lng, lat)
         opts.onInitPosition(result)
      }
   }

   /**---------------------------------------根据插件，暴露出接口给用户使用---------------------------------------*/

   // Geocoder-根据经纬度获取地址信息
   private getGeocoderAddress = async (lng: number, lat: number): GetAddressReturnType => {
      return new Promise((resolve, reject) => {
         this.Geocoder.getAddress([lng, lat], function (status, result) {
            if (status === 'complete' && result.info === 'OK') {
               resolve({
                  citycode: result.regeocode.citycode,
                  address: result.regeocode.formattedAddress,
                  lng,
                  lat
               } as ClickInfo)
            }
            reject(null)
         });
      })
   }

   // MSearch-关键词查询
   searchPlace = async (keyword: string) => {
      return new Promise((resolve, reject) => {
         this.MSearch.search(keyword, (status, result) => {
            console.log(result)
            if (status === 'complete') {
               // 根据不同情况返回不同信息
               switch (result.info) {
                  case 'OK': {
                     const { count, pageIndex, pageSize, pois } = result.poiList
                     this.MSearch.pagination = new Pagination({
                        count, pageIndex, pageSize
                     })
                     this.MSearch.keyword = keyword
                     resolve({
                        type: 'address',
                        list: pois,
                        hasNextPage: this.MSearch.pagination.hasNextPage()
                     })
                     break
                  }
                  // 要求你缩小范围
                  case 'TIP_CITIES': {
                     resolve({
                        type: 'tip',
                        list: result.cityList,
                        hasNextPage: false
                     })
                     break
                  }
                  default:
                     break


               }

            }
            resolve(emptyResults)
         }); //关键字查询
      })
   }

   searchNextPage = async () => {
      return new Promise((resolve, reject) => {
         const nextPageIndex = this.MSearch.pagination.nextPage()
         if (nextPageIndex) {
            this.MSearch.setPageIndex(nextPageIndex)
            this.MSearch.search(this.MSearch.keyword, (status, result) => {
               if (status === 'complete' && result.info === 'OK') {
                  const { pois } = result.poiList
                  resolve({
                     type: 'address',
                     list: pois,
                     hasNextPage: this.MSearch.pagination.hasNextPage()
                  })
               }
               resolve(emptyResults)
            }); //关键字查询
         } else {
            resolve(emptyResults)
         }
      })
   }

   /**---------------------------------------其他私有方法---------------------------------------*/
}

export default GdMap